/**
 * @file        interface.hpp
 * @brief       Command line interface handling.
 *
 * @author      Emre Turkay <emreturkay at gmail>
 * @date        May.31.2008
 *
 * Copyright Emre Turkay 2009
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file COPYRIGHT or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef _INTERFACE_HPP_
#define _INTERFACE_HPP_

#include <boost/function.hpp>

#include <map>
#include <vector>
#include <string>
#include <iostream>

namespace rl { struct reader; }

/// Interface action.
struct action_info
{
    /// Arguments type provided to the command handler function.
    typedef std::vector<std::string> args_type;
    /// The command handler function type.
    typedef boost::function<void(const args_type&)> function_type;
    /// The tab completer function type.
    typedef boost::function<std::vector<std::string>(const args_type&, bool)>
        completer_type;

    /// Empty default constructor.
    action_info() { }
    /// Constructor with the command handler function and description.
    action_info(function_type f, const std::string& desc = "");

    /// Setter for the tab completion function.
    void completer(completer_type c) { completer_ = c; }

    /// The execute method of the action.
    void operator()(const args_type& args);

    /// Getter for the command description.
    const std::string& description() const { return description_; }

    /// Tab completion executor function.
    std::vector<std::string>
    complete(const std::vector<std::string>& args, bool complete);

private:
    /// Command handler function.
    function_type function_;
    /// Tab completion function.
    completer_type completer_;
    /// Command description.
    std::string description_;
};

/// A generic class for command line interface handling.
struct interface
{
    /// The arguments send to the command handler.
    typedef action_info::args_type args_type;
    /// The command handler function type.
    typedef action_info::function_type function_type;
    /// The tab completion function type.
    typedef action_info::completer_type completer_type;
    /// Information construct about the action.
    typedef std::map<std::string, action_info> actions_type;

    /// Constructor, initializes GNU readline.
    interface();

    /**
     * @brief Add a new command.
     * @param text          The command text.
     * @param action        The command handler function.
     * @param description   Optional description.
     */
    void command(const std::string& text,
                 function_type action,
                 const std::string& description = "");

    /**
     * Sets a tab completion function.
     * @param text  The command to set tab completion function.
     * @param text  The tab completion function.
     */
    void set_completer(const std::string& text, completer_type completer);

    /// Iterative main loop, returns false on quit.
    bool process();

    /// Show help.
    void help();

    /// Write message to the output.
    void write(const std::string& value);

    /// The completer callback function (called by readline).
    std::vector<std::string>
    completer(const std::vector<std::string>& args, bool complete);

private:
    /// The reference to the readline.
    rl::reader& reader_;
    /// The actions container.
    actions_type actions_;
};

/// Help command, shows help.
struct help_command
{
    help_command(interface& intf)
        : intf_(intf)
    {
    }

    void operator()(const interface::args_type&)
    {
        intf_.help();
    }

private:
    interface& intf_;
};

#endif // _INTERFACE_HPP_
